﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using GeckoPhotos.Repository;
using GeckoPhotos.Models;
using System.IO;
using GeckoPhotos.Util;

namespace GeckoPhotos.Service
{
    public class ImageServiceLayer
    {
        private readonly IImageRepository _repository;
        private readonly IUserRepository _userRepository;

        public ImageServiceLayer() :
            this(null)
        {
        }

        public ImageServiceLayer(IImageRepository repository)
        {
            _repository = repository ?? new EFImageRepository();
        }

        public ImageServiceLayer(IImageRepository repository, IUserRepository optionalUserRepository)
        {
            _repository = repository ?? new EFImageRepository();
            _userRepository = optionalUserRepository;
        }

        /// <summary>
        /// Ensures that all referenced objects have been loaded; used to make sure
        /// the repository fetches foreign objects when required by the service.
        /// </summary>
        /// <param name="image"></param>
        protected static void EnsureReferencesFetched(Image image)
        {
            if (image.User == null)
                throw new InvalidOperationException();
            if (image.Blob == null)
                throw new InvalidOperationException();
        }

        public IEnumerable<Image> GetAll()
        {
            return _repository.All();
        }

        public Image GetById(int imageId)
        {
            var result = _repository.Where(i => i.ImageID == imageId).FirstOrDefault();
            if (result == null)
                return null;

            EnsureReferencesFetched(result);

            return result;
        }

        public Image Insert(ISettings settings, string caption, byte[] bytes, string username)
        {
            if (_userRepository == null)
                throw new InvalidOperationException("An IUserRepository must be specified during construction if calling Insert().");

            Blob blob = new Blob
            {
                Bytes = ImageUtil.CreateResizedImageToFitWidthHeight(
                    settings.MaxImageWidth,
                    settings.MaxImageHeight,
                    bytes,
                    settings.StandardImageFormat
                ),
                MimeType = Util.ImageUtil.GetMimeType(settings.StandardImageFormat),
            };

            Blob thumbnailBlob = new Blob
            {
                Bytes = ImageUtil.CreateResizedImageToFitWidthHeight(
                    settings.ThumbnailWidth,
                    settings.ThumbnailHeight,
                    bytes,
                    settings.StandardImageFormat
                ),
                MimeType = Util.ImageUtil.GetMimeType(settings.StandardImageFormat),
            };

            User user = _userRepository.Single(u => u.Username == username);

            Image image = new Image
            {
                DateTimeCreated = DateTime.UtcNow,
                Caption = caption ?? string.Empty,
            };

            Message message = new Message
            {
                DateTime = DateTime.UtcNow,
                InstigatorUser = user,
                MessageTypeID = (int)MessageTypeEnum.ImageCreated,
                Text = Properties.Resources.MessageImageUploaded,
            };

            image.Blob = blob;
            image.ThumbnailBlob = thumbnailBlob;
            image.User = user;
            image.Messages.Add(message);

            _repository.Insert(image);

            return image;
        }

        public void Delete(int imageId)
        {
            // Create a "stub" image with the key to be deleted
            Image image = new Image { ImageID = imageId };

            _repository.Remove(image);
        }

        public Image GetByIdWithMessages(int imageId)
        {
            return _repository.SingleWithMessages(imageId);
        }
    }
}